<?php
def("amicitia/persistencia/daos/","DaoQuiniela");
def("amicitia/persistencia/daos/","ConexionBD");
def("amicitia/modelo/entidades/","Quiniela");
def("amicitia/modelo/entidades/","Persona");
def("amicitia/modelo/entidades/","Pareja");
def("amicitia/modelo/entidades/","Juego");
def("amicitia/persistencia/excepciones/","IntegridadDatosException");

/**
 * Maneja todas las consideraciones de persistencia en MySql para con la
 * entidad Quiniela.
 * 
 * @author Willy A. Kuster
 */
class DaoQuinielaMySql implements DaoQuiniela {

	const SELECT_QUINIELA = "SELECT id, id_juego_fk, id_apostador_fk FROM quiniela WHERE id=%s";
	const SELECT_QUINIELA_JUEGO_PERSONA = "SELECT id, id_juego_fk, id_apostador_fk FROM quiniela WHERE id_juego_fk=%s AND id_apostador_fk=%s";
	const INSERT_QUINIELA = "INSERT INTO quiniela (id,id_juego_fk,id_apostador_fk) VALUES (%s,%s,%s)";
	const DELETE_QUINIELA = "DELETE FROM quiniela WHERE id=%s";
	const SELECT_QUINIELA_PAREJA = "SELECT id_quiniela_fk, id_pareja_fk FROM quiniela_pareja WHERE id_quiniela_fk=%s";
	const INSERT_QUINIELA_PAREJA = "INSERT INTO quiniela_pareja (id_quiniela_fk,id_pareja_fk) VALUES (%s,%s)";

	private $conexion;

	public function __construct() {
		$this->conexion = ConexionBD::getConexionBD();
		//$this->conexion->conectar();
	}

	/**
	 * @see persistencia/daos/DaoQuiniela#obtenerQuiniela($id)
	 */
	public function obtenerQuiniela($id) {
		
		$id = $this->conexion->escaparCadena($id);
		$query = sprintf(self::SELECT_QUINIELA,$id);
		$result = $this->conexion->seleccionar($query);

		if($obj = $result->fetch_object()){
			$quiniela = $this->generarQuiniela($obj);

			$result->close();

			return $quiniela;
		} else {
			return NULL;
		}
		
	}
	
	/**
	 * @see persistencia/daos/DaoQuiniela#obtenerQuinielaDeJuegoYPersona($juego, $persona)
	 */
	public function obtenerQuinielaDeJuegoYPersona(Juego $juego,Persona $persona) {
		$id_juego_fk = $this->conexion->escaparCadena($juego->getId());
		$id_apostador_fk = $this->conexion->escaparCadena($persona->getId());
		$query = sprintf(self::SELECT_QUINIELA_JUEGO_PERSONA,$id_juego_fk,$id_apostador_fk);
		$result = $this->conexion->seleccionar($query);

		if ($obj = $result->fetch_object()) {
			$quiniela = $this->generarQuiniela($obj);

			$result->close();

			return $quiniela;
		} else {
			return NULL;
		}
	}
	
	/**
	 * Crea un objeto Quiniela a partir de un resultado de base de datos.
	 * 
	 * @param $obj
	 * 			Un objeto proveniente de la llamada $result->fetch_object().
	 * @return Quiniela
	 * 			Un objeto Quiniela.
	 */
	private function generarQuiniela($obj) {
		$quiniela = new Quiniela();
		$quiniela->setId($obj->id);
		
		$fabricaDao = FabricaDao::obtenerFabrica();
		$daoPersona = $fabricaDao->obtenerDaoPersona();
		$quiniela->setApostador($daoPersona->obtenerPersona($obj->id_apostador_fk));
		
		$quiniela->setPosiblesParejas($this->obtenerParejasDeQuiniela($obj->id));
		
		return $quiniela;
	}
	
	/**
	 * Obtiene las parejas de una Quiniela.
	 * 
	 * @param $id
	 * 			El id de una Quiniela.
	 * @return array(Pareja)
	 * 			Un arreglo de parejas.
	 */
	private function obtenerParejasDeQuiniela($id) {
		$id = $this->conexion->escaparCadena($id);
		$query = sprintf(self::SELECT_QUINIELA_PAREJA,$id);
		$result = $this->conexion->seleccionar($query);
		$fabricaDao = FabricaDao::obtenerFabrica();
		$daoPareja = $fabricaDao->obtenerDaoPareja();
		while ($obj = $result->fetch_object()) {
			$parejas[$obj->id_pareja_fk] = $daoPareja->obtenerPareja($obj->id_pareja_fk);
		}
		return $parejas;
	}
	
	/**
	 * @see persistencia/daos/DaoQuiniela#guardarQuiniela($quiniela)
	 */
	public function guardarQuiniela(Quiniela $quiniela,Juego $juego) {
		
		$this->verificarQuinielaYJuego($quiniela,$juego);
		
		$id = is_null($quiniela->getId()) ? "NULL" : (int)$this->conexion->escaparCadena($quiniela->getId());
		$id_juego_fk = (int)$this->conexion->escaparCadena($juego->getId());
		$id_apostador_fk = (int)$this->conexion->escaparCadena($quiniela->getApostador()->getId());
		
		$query = sprintf(self::INSERT_QUINIELA,$id,$id_juego_fk,$id_apostador_fk);
		$id = $this->conexion->insertar($query);
		
		$fabricaDao = FabricaDao::obtenerFabrica();
		$daoPareja = $fabricaDao->obtenerDaoPareja();
		
		$parejas = $quiniela->getPosiblesParejas();
		foreach ($parejas as $pareja) {
			$idPareja = $daoPareja->guardarPareja($pareja);
			$query = sprintf(self::INSERT_QUINIELA_PAREJA,$id,$idPareja);
			$this->conexion->insertar($query);
		}
		
		return $id;
		
	}
	
	/**
	 * @see persistencia/daos/DaoQuiniela#eliminarQuiniela($id)
	 */
	public function eliminarQuiniela($id) {
		
		$id = $this->conexion->escaparCadena($id);
		$query = sprintf(self::DELETE_QUINIELA,$id);
		$afectados = $this->conexion->actualizarOEliminar($query);
		
		if ($afectados==1) {
			return true;
		} else {
			return false;
		}
		
	}
	
	/**
	 * Verifica la integridad de los objeto Quiniela y Juego que se pasen por parámetro.
	 * 
	 * @param $quiniela
	 * 			Un objeto Quiniela.
	 * @param $juego
	 * 			Un objeto Juego.
	 */
	private function verificarQuinielaYJuego(Quiniela $quiniela,Juego $juego) {
		if(is_null($quiniela->getApostador()))
			throw new IntegridadDatosException(get_class($quiniela),"apostador",$quiniela->getApostador());
		if(is_null($quiniela->getApostador()->getId()))
			throw new IntegridadDatosException(get_class($quiniela->getApostador()),"id",$quiniela->getApostador()->getId());
		if(is_null($quiniela->getPosiblesParejas()))
			throw new IntegridadDatosException(get_class($quiniela),"posiblesPaerjas",$quiniela->getPosiblesParejas());
		if(count($quiniela->getPosiblesParejas())==0)
			throw new IntegridadDatosException(get_class($quiniela),"posiblesPaerjas",$quiniela->getPosiblesParejas(), "Debe haber al menos una posible 'Pareja' en una 'Quiniela'");
		if(is_null($juego->getId()))
			throw new IntegridadDatosException(get_class($juego),"id",$juego->getId());
		
		foreach($quiniela->getPosiblesParejas() as $pareja){
			if($quiniela->getApostador()==$pareja->getDador())
				throw new IntegridadDatosException(get_class($quiniela),"apostador",$quiniela->getApostador(),"Un jugador no puede apostar por sí mismo");
		}
	}
	
}
?>